﻿////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  © 2012 Stanislav S. Yarmonov.
//
//  TODO:LICENSE
//     
////////////////////////////////////////////////////////////////////////////////////////////////////
using System;
using System.Data;
using System.Data.Common;
using System.Configuration;

namespace Pandora.Data.Common
{
    ////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary>
    /// Database connection factory.
    /// </summary>
    /// <remarks>
    /// Database connection factory is similair to database provider factory with one improvement,
    /// that it is bound to concrete database, so it contains connection settings.
    /// </remarks>
    ////////////////////////////////////////////////////////////////////////////////////////////////
    public class DbConnectionFactory
    {
        private DbProviderFactory _Factory = null;
        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Database provider factory.
        /// </summary>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public DbProviderFactory Factory
        {
            get
            {
                return _Factory;
            }
        }

        private string _ConnectionString = null;
        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Database connection string.
        /// </summary>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public string ConnectionString
        {
            get
            {
                return _ConnectionString;
            }
            set
            {
                _ConnectionString = value;
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Stored procedure command creation routine.
        /// </summary>
        /// <param name="name">
        /// Stored procedure name.
        /// </param>
        /// <returns>
        /// Returns database command class for stored procedure.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public IDbCommand Procedure(string name)
        {
            return _Factory
                .Procedure(name)
                .Connection(_ConnectionString);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Table access command creation routine.
        /// </summary>
        /// <param name="name">
        /// Table name.
        /// </param>
        /// <returns>
        /// Returns database command class for table.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public IDbCommand Table(string name)
        {
            return _Factory
                .Table(name)
                .Connection(_ConnectionString);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Database query command creation routine.
        /// </summary>
        /// <param name="text">
        /// Stored procedure name.
        /// </param>
        /// <returns>
        /// Returns database command class for stored procedure.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public IDbCommand Query(string text)
        {
            return _Factory
                .Query(text)
                .Connection(_ConnectionString);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="factory">
        /// Database provider factory to create the connection factory for.
        /// </param>
        ////////////////////////////////////////////////////////////////////////////////////////////
        private DbConnectionFactory(DbProviderFactory factory)
        {
            _Factory = factory;
        }

        ////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>
        /// Create database connection factory from connection setting name.
        /// </summary>
        /// <param name="name">
        /// Name of the connection strings setting in the application configuration file.
        /// </param>
        /// <returns>
        /// Returns database connection factory created.
        /// </returns>
        ////////////////////////////////////////////////////////////////////////////////////////////
        public static DbConnectionFactory Config(string name)
        {
            string hostName = string.Concat(name, ".", Environment.MachineName);
            ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings[hostName];
            if (settings == null)
            {
                settings = ConfigurationManager.ConnectionStrings[name];
            }
            //TODO:Check for connection string existence

            if (settings == null)
            {
                throw new Exception(string.Format("Connection string [{0}] not found in config", name)); //TODO:
            }

            //TODO:if not found
            DbProviderFactory factory = DbProviderFactories.GetFactory(settings.ProviderName) as DbProviderFactory;

            return new DbConnectionFactory(factory)
            {
                ConnectionString = settings.ConnectionString
            };
        }
    }
}
